diff options
| author | it-fixcomart <it@fixcomart.co.id> | 2024-09-04 09:54:44 +0700 |
|---|---|---|
| committer | it-fixcomart <it@fixcomart.co.id> | 2024-09-04 09:54:44 +0700 |
| commit | f6a398c036d2ab833ecb798fa88e641e2f801bb0 (patch) | |
| tree | 7aead541e26b5166ae3d2049fc732c7030e4e9c6 /src/pages/shop/promo/[slug].jsx | |
| parent | cbdeecd2fb8770afe46a374292e6ed3e5ec48214 (diff) | |
| parent | ad168bf46919b46f708625b7d2fdc56606ec9af6 (diff) | |
Merge branch 'update-allPromo-fetch' into backup-release
Diffstat (limited to 'src/pages/shop/promo/[slug].jsx')
| -rw-r--r-- | src/pages/shop/promo/[slug].jsx | 394 |
1 files changed, 394 insertions, 0 deletions
diff --git a/src/pages/shop/promo/[slug].jsx b/src/pages/shop/promo/[slug].jsx new file mode 100644 index 00000000..cfb2c841 --- /dev/null +++ b/src/pages/shop/promo/[slug].jsx @@ -0,0 +1,394 @@ +import dynamic from 'next/dynamic' +import NextImage from 'next/image'; +import { useEffect, useState } from 'react' +import { useRouter } from 'next/router' +import Seo from '../../../core/components/Seo.jsx' +import Promocrumb from '../../../lib/promo/components/Promocrumb.jsx' +import LogoSpinner from '../../../core/components/elements/Spinner/LogoSpinner.jsx' +import ProductPromoCard from '../../../../src-migrate/modules/product-promo/components/Card.tsx' +import React from 'react' +import DesktopView from '../../../core/components/views/DesktopView.jsx'; +import MobileView from '../../../core/components/views/MobileView.jsx'; +import 'swiper/swiper-bundle.css'; +import useDevice from '../../../core/hooks/useDevice.js' +import ProductFilterDesktop from '../../../lib/product/components/ProductFilterDesktopPromotion.jsx'; +import ProductFilter from '../../../lib/product/components/ProductFilter.jsx'; +import { HStack, Image, Tag, TagCloseButton, TagLabel } from '@chakra-ui/react'; +import { formatCurrency } from '../../../core/utils/formatValue.js'; +import Pagination from '../../../core/components/elements/Pagination/Pagination.js'; +import whatsappUrl from '../../../core/utils/whatsappUrl.js'; +import _ from 'lodash'; +import useActive from '../../../core/hooks/useActive.js'; +import useProductSearch from '../../../lib/promo/hooks/usePromotionSearch.js'; + +const BasicLayout = dynamic(() => import('../../../core/components/layouts/BasicLayout.jsx')) + +export default function PromoDetail() { + const router = useRouter() + const { slug = '', brand ='', category='', page = '1' } = router.query + const [currentPage, setCurrentPage] = useState(parseInt(10) || 1); + const [orderBy, setOrderBy] = useState(router.query?.orderBy); + const popup = useActive(); + const prefixUrl = `/shop/promo/${slug}` + const [queryFinal, setQueryFinal] = useState({}); + const [limit, setLimit] = useState(30); + const [q, setQ] = useState('*'); + const [finalQuery, setFinalQuery] = useState({}); + const [products, setProducts] = useState(null); + const [brandValues, setBrand] = useState( + !router.pathname.includes('brands') + ? router.query.brand + ? router.query.brand.split(',') + : [] + : [] + ); + + const [categoryValues, setCategory] = useState( + router.query?.category?.split(',') || router.query?.category?.split(',') + ); + + const [priceFrom, setPriceFrom] = useState(router.query?.priceFrom || null); + const [priceTo, setPriceTo] = useState(router.query?.priceTo || null); + + + useEffect(() => { + const newQuery = { + fq: `type_value_s:${slug}`, + page : router.query.page? router.query.page : 1, + brand : router.query.brand? router.query.brand : '', + category : router.query.category? router.query.category : '', + priceFrom : router.query.priceFrom? router.query.priceFrom : '', + priceTo : router.query.priceTo? router.query.priceTo : '', + limit : router.query.limit? router.query.limit : '', + orderBy : router.query.orderBy? router.query.orderBy : '' + }; + setFinalQuery(newQuery); +}, [router.query, prefixUrl, slug, brand, category, priceFrom, priceTo, currentPage]); + useEffect(() => { + setQueryFinal({ ...finalQuery, q, limit, orderBy }); + }, [router.query, prefixUrl, slug, brand, category, priceFrom, priceTo, currentPage, finalQuery]); + + const { productSearch } = useProductSearch({ + query: queryFinal, + operation: 'OR', + }); + + + const pageCount = Math.ceil(productSearch.data?.response.numFound / limit); + const productStart = productSearch.data?.responseHeader.params.start; + const productRows = limit; + const productFound = productSearch.data?.response.numFound; + + useEffect(() => { + setProducts(productSearch.data?.response?.products); + }, [productSearch]); + + const brands = []; + for ( + let i = 0; + i < productSearch.data?.facet_counts?.facet_fields?.manufacture_name_s.length; + i += 2 + ) { + const brand = + productSearch.data?.facet_counts?.facet_fields?.manufacture_name_s[i]; + const qty = + productSearch.data?.facet_counts?.facet_fields?.manufacture_name_s[i + 1]; + if (qty > 0) { + brands.push({ brand, qty }); + } + } + + const categories = []; + for ( + let i = 0; + i < productSearch.data?.facet_counts?.facet_fields?.category_name.length; + i += 2 + ) { + const name = productSearch.data?.facet_counts?.facet_fields?.category_name[i]; + const qty = + productSearch.data?.facet_counts?.facet_fields?.category_name[i + 1]; + if (qty > 0) { + categories.push({ name, qty }); + } + } + + function capitalizeFirstLetter(string) { + string = string.replace(/_/g, ' '); + return string.replace(/(^\w|\s\w)/g, function(match) { + return match.toUpperCase(); + }); + } + + const handleDeleteFilter = async (source, value) => { + let params = { + q: router.query.q, + orderBy: '', + brand: brandValues.join(','), + category: categoryValues?.join(','), + priceFrom: priceFrom || '', + priceTo: priceTo || '', + }; + + let brands = brandValues; + let catagories = categoryValues; + switch (source) { + case 'brands': + brands = brandValues.filter((item) => item !== value); + params.brand = brands.join(','); + await setBrandValues(brands); + break; + case 'category': + catagories = categoryValues.filter((item) => item !== value); + params.category = catagories.join(','); + await setCategoryValues(catagories); + break; + case 'price': + params.priceFrom = ''; + params.priceTo = ''; + break; + case 'delete': + params = { + q: router.query.q, + orderBy: '', + brand: '', + category: '', + priceFrom: '', + priceTo: '', + }; + break; + } + + handleSubmitFilter(params); + }; + const handleSubmitFilter = (params) => { + params = _.pickBy(params, _.identity); + params = toQuery(params); + router.push(`${slug}?${params}`); + }; + + + const toQuery = (obj) => { + const str = Object.keys(obj) + .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`) + .join('&') + return str + } + + const whatPromo = capitalizeFirstLetter(slug) + const queryWithoutSlug = _.omit(router.query, ['slug']) + + return ( + <BasicLayout> + <Seo + title={`Promo ${Array.isArray(slug) ? slug[0] : slug} Terkini`} + description='B2B Marketplace MRO & Industri dengan Layanan Pembayaran Tempo, Faktur Pajak, Online Quotation, Garansi Resmi & Harga Kompetitif' + /> + <Promocrumb brandName={whatPromo} /> + <MobileView> + <div className='p-4 pt-0'> + <h1 className='mb-2 font-semibold text-h-sm'>Promo {whatPromo}</h1> + + <FilterChoicesComponent + brandValues={brandValues} + categoryValues={categoryValues} + priceFrom={priceFrom} + priceTo={priceTo} + handleDeleteFilter={handleDeleteFilter} + /> + {products?.length >= 1 && ( + <div className='flex items-center gap-x-2 mb-5 justify-between'> + <div> + <button + className='btn-light py-2 px-5 h-[40px]' + onClick={popup.activate} + > + Filter + </button> + </div> + </div> + )} + {productSearch.isLoading && <div className='container flex justify-center my-4'> + <LogoSpinner width={48} height={48} /> + </div>} + {products && ( + <> + <div className='grid grid-cols-1 gap-x-1 gap-y-1'> + {products?.map((promotion) => ( + <div key={promotion.id} className="min-w-36 max-w-[400px] mb-[20px] sm:w-full md:w-1/2 lg:w-1/3 xl:w-1/4 "> + <ProductPromoCard promotion={promotion}/> + </div> + ))} + </div> + </> + ) } + + <Pagination + pageCount={pageCount} + currentPage={parseInt(page)} + url={`${prefixUrl}?${toQuery(_.omit(queryWithoutSlug, ['page']))}`} + className='mt-6 mb-2' + /> + <ProductFilter + active={popup.active} + close={popup.deactivate} + brands={brands || []} + categories={categories || []} + prefixUrl={router.asPath.includes('?') ? `${router.asPath}` : `${router.asPath}?`} + defaultBrand={null} + /> + </div> + + </MobileView> + <DesktopView> + <div className='container mx-auto flex mb-3 flex-col'> + <div className='w-full pl-6'> + <h1 className='text-2xl mb-2 font-semibold'>Promo {whatPromo}</h1> + <div className=' w-full h-full flex flex-row items-center '> + + <div className='detail-filter w-1/2 flex justify-start items-center mt-4'> + + <FilterChoicesComponent + brandValues={brandValues} + categoryValues={categoryValues} + priceFrom={priceFrom} + priceTo={priceTo} + handleDeleteFilter={handleDeleteFilter} + /> + </div> + <div className='Filter w-1/2 flex flex-col'> + + <ProductFilterDesktop + brands={brands || []} + categories={categories || []} + prefixUrl={'/shop/promo'} + // defaultBrand={null} + /> + </div> + </div> + {productSearch.isLoading ? ( + <div className='container flex justify-center my-4'> + <LogoSpinner width={48} height={48} /> + </div> + ) : products && products.length >= 1 ? ( + <> + <div className='grid grid-cols-1 gap-x-6 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-3'> + {products?.map((promotion) => ( + <div key={promotion.id} className="min-w-[400px] max-w-[400px] mb-[20px] sm:min-w-[350px] md:min-w-[380px] lg:min-w-[400px] xl:min-w-[400px] "> + <ProductPromoCard promotion={promotion}/> + </div> + ))} + </div> + </> + ) : ( + <div className="text-center my-8"> + <p>Belum ada promo pada kategori ini</p> + </div> + )} + <div className='flex justify-between items-center mt-6 mb-2'> + <div className='pt-2 pb-6 flex items-center gap-x-3'> + <NextImage + src='/images/logo-question.png' + alt='Logo Question Indoteknik' + width={60} + height={60} + /> + <div className='text-gray_r-12/90'> + <span> + Barang yang anda cari tidak ada?{' '} + <a + href={ + router.query?.q + ? whatsappUrl('productSearch', { + name: router.query.q, + }) + : whatsappUrl() + } + className='text-danger-500' + > + Hubungi Kami + </a> + </span> + </div> + </div> + + + + <Pagination + pageCount={pageCount} + currentPage={parseInt(page)} + url={`${prefixUrl}?${toQuery(_.omit(queryWithoutSlug, ['page']))}`} + className='mt-6 mb-2' + /> + </div> + + </div> + </div> + </DesktopView> + </BasicLayout> + ) + } + +const FilterChoicesComponent = ({ + brandValues, + categoryValues, + priceFrom, + priceTo, + handleDeleteFilter, + }) => ( + <div className='flex items-center mb-4'> + <HStack spacing={2} className='flex-wrap'> + {brandValues?.map((value, index) => ( + <Tag + size='lg' + key={index} + borderRadius='lg' + variant='outline' + colorScheme='gray' + > + <TagLabel>{value}</TagLabel> + <TagCloseButton onClick={() => handleDeleteFilter('brands', value)} /> + </Tag> + ))} + + {categoryValues?.map((value, index) => ( + <Tag + size='lg' + key={index} + borderRadius='lg' + variant='outline' + colorScheme='gray' + > + <TagLabel>{value}</TagLabel> + <TagCloseButton + onClick={() => handleDeleteFilter('category', value)} + /> + </Tag> + ))} + {priceFrom && priceTo && ( + <Tag size='lg' borderRadius='lg' variant='outline' colorScheme='gray'> + <TagLabel> + {formatCurrency(priceFrom) + '-' + formatCurrency(priceTo)} + </TagLabel> + <TagCloseButton + onClick={() => handleDeleteFilter('price', priceFrom)} + /> + </Tag> + )} + {brandValues?.length > 0 || + categoryValues?.length > 0 || + priceFrom || + priceTo ? ( + <span> + <button + className='btn-transparent py-2 px-5 h-[40px] text-red-700' + onClick={() => handleDeleteFilter('delete')} + > + Hapus Semua + </button> + </span> + ) : ( + '' + )} + </HStack> + </div> +); |
